#pragma once
// 用户管理模块
#include <string>
#include<iostream>
#include <unordered_map>
#include"../comm/util.hpp"
#include "../include/mysql.h"

namespace ns_user
{
    using namespace ns_until;
    // 用户模块 先将数据库中存在的所有用户缓存到内存中来，这样每次就不需要访问数据库了
    struct UserObject
    {
        std::string id;  // 用户账号
        std::string password;  // 用户密码
        bool root = false;  // 用户管理权限 默认不是
    };

    const std::string oj_table_name = "oj_questions";
    const std::string oj_host = "43.143.4.250";
    const std::string oj_user = "oj_client";
    const std::string oj_password = "123456";
    const std::string oj_db = "oj";
    const unsigned int oj_port = 3306;

    class User
    {
    public:
        std::unordered_map<std::string, std::string> _sessions;  // 存储会话数据的哈希表

        User()
        {}
        ~User()
        {}

        // 1 数据库连接失败
        // 2 执行结果报错 -注意select 查找不到不会报错
        int QueryMySqlResult(const std::string& sql, MYSQL_RES*& res)
        {
            // c连接mysql库，创建mysql对象-初始化mysql句柄
            MYSQL* oj_client = mysql_init(nullptr);
            // 连接数据库，连接失败返回nullptr
            if (nullptr == mysql_real_connect(oj_client, oj_host.c_str(), oj_user.c_str(), oj_password.c_str(), oj_db.c_str(), oj_port, nullptr, 0))
            {
                // 表示连接数据库失败
                std::cout<< "数据库连接失败！请尽快联系数据库管理员....." << "\n";
                return 1;
            }
            // 连接成功后先执行编码格式
            mysql_set_character_set(oj_client, "utf8");

            // 连接成功后执行语句
            int result = mysql_query(oj_client, sql.c_str());
            if (result != 0)
            {
                // 执行失败 sql语句的错误
                // LOG(WARING) << "sql语句存在错误：" << sql << "\n";
                return 2;
            }
            // 执行成功，提取数据
            res = mysql_store_result(oj_client);
            // 上层解析数据
            return 0;
        }

        // 0-查找成功，存在此用户
        // 1-内部错误
        // 2-用户名错误或不存在
        // 3-密码错误
        // 4-权限错误 测试
        int FindUser(const std::string& user_name, const std::string& password)
        {
            MYSQL_RES* res1 = nullptr;
            if (user_name == "") return 2;  // 为空
            std::string sql = "select * from oj_user where id='" + user_name + "';";
            if(0 != QueryMySqlResult(sql, res1)) return 1;

            MYSQL_ROW line1 = mysql_fetch_row(res1);
            if (line1 == 0){
                // 用户不存在或者没找到
                return 2;
            }

            MYSQL_RES* res2 = nullptr;
            // 第二次执行sql
            sql = "select * from oj_user where id='" + user_name + \
                "' and `password`=password('" + password + "');";
            if(0 != QueryMySqlResult(sql, res2)) return 3;

            MYSQL_ROW line2 = mysql_fetch_row(res2);
            if (line2 == 0){
                // 密码错误
                return 3;
            } 

            // UserObject user;
            // user.id = line2[0];
            // user.password = line2[1];
            // user.root = line2[2];
            return 0;
        }

        // 注册用户
        // 0 注册成功
        // 1 内部错误
        // 2 用户名为空或者已经存在
        // 3 密码格式错误
        int RegisterUser(const std::string& user_name, const std::string& password)
        {
            MYSQL_RES* res = nullptr;
            if (user_name == "") return 2;  // 为空
            std::string sql = "select * from oj_user where id='" + user_name + "';";
            if(0 != QueryMySqlResult(sql, res)) return 1;  // 内部出错

            MYSQL_ROW line = mysql_fetch_row(res);
            if (line == 0){
                // 用户找不到，可以插入
                sql = "insert into oj_user(id, password) values('" + user_name + "', password('" + password + "'));";
                int op = QueryMySqlResult(sql, res);
                if (op == 1) return 1;  // 连接出错
                else if (op == 2) return 3;  // 密码格式问题
            }
            else return 2;  // 用户名冲突

            return 0;
        }

        // 修改密码
        bool ChangePassWord(const std::string& user_name, const std::string& password)
        {
            MYSQL_RES* res = nullptr;
            std::string sql = "update oj_user set `password` = password('" + password + "') where id = " + user_name + ";";
            int op = QueryMySqlResult(sql, res);
            return !op;
        }

        // 生成一个随机的会话 ID
        std::string GenerateSessionId() {
            static const char alphanum[] =
                "0123456789"
                "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                "abcdefghijklmnopqrstuvwxyz";
            
            const int id_length = 10;
            std::string session_id;
            for (int i = 0; i < id_length; ++i) {
                session_id += alphanum[rand() % (sizeof(alphanum) - 1)];
            }
            session_id += FileUtil::UniqFileName();
            return session_id;
        }

        // 根据会话ID查找用户信息
        bool FindCookidUser(const std::string& session_id)
        {
            auto it = _sessions.find(session_id);
            return it != _sessions.end();
        }

        
    };
}
